﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using WebArchivosTelefonica.Jerarquias;
using System.Collections.ObjectModel;
using System.IO;

namespace WebArchivosTelefonica.Jerarquias
{
    /// <summary>
    /// Administrador de fuentes de datos
    /// </summary>
    public class Administrador : IAdministrador, IDisposable
    {
        private IFabricaLinqDataSource _fabricaLinqDataSource;
        private const string _nombreEntidadSitio = "Sitios";
        private const string _nombreEntidadCandidato = "Candidatos";
        private const string _nombreEntidadDocumento = "Documentos";
        private const string _nombreEntidadCliente = "Clientes";
        private const string _nombreEntidadProyect = "Proyectos";
        private IEntidadLinqDataContext _contexto;

        /// <summary>
        /// Constructor por defecto
        /// </summary>
        public Administrador(IFabricaLinqDataSource fabricaLinqDataSource, IEntidadLinqDataContext contexto)
        {
            _fabricaLinqDataSource = fabricaLinqDataSource;
            _contexto = contexto;
        }

        /// <summary>
        /// Retorna el id de un estado seleccionado de un proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <returns>Retorna el id del estado seleccionado como string en caso de no haber estado seleccionado retorna "- - -"</returns>
        public string GetEstadoSeleccionadoProyecto(Guid idProyecto)
        {
            return _contexto.GetEstadoSeleccionadoProyecto(idProyecto);
        }


        /// <summary>
        /// Retorna un DataSource de Sitios desde la base de datos
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto al que pertenece el sitio</param>
        /// <returns>DataSource Sitios</returns>
        public ListItemCollection GetDataSourceSitios(string idProyecto)
        {
            ListItemCollection resultado = new ListItemCollection();
            if (idProyecto != null && idProyecto != "- - -")
                resultado = _contexto.GetSitiosByIdProyecto(idProyecto);
            return resultado;
        }

        /// <summary>
        /// Retorna un DataSource de Candidatos para el Sitio indicado
        /// </summary>
        /// <param name="idSitio">Identificador del Sitio</param>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <returns>DataSource Candidatos</returns>
        public ListItemCollection GetDataSourceCandidatos(string idSitio, string idProyecto)
        {
            ListItemCollection resultado = new ListItemCollection();
            if (idProyecto != null && idProyecto != "- - -")
                resultado = _contexto.GetCandidatosByIdSitioIdProyecto(idSitio, idProyecto);
            return resultado;
        }

        /// <summary>
        /// Retorna el Id de la carpeta otros si exise en una jerarquia de carpetas dada
        /// </summary>
        /// <param name="idCarpeta">Id de la carpeta en donde se va a buscar la carpeta otros</param>
        /// <returns>Id de la carpeta otros si existe</returns>
        public Guid GetIdCarpetaOtros(Guid idCarpeta)
        {
            IEntidadLinqJerarquiaCarpeta jerarquiaCarpeta = _contexto.GetJerarquiaById(idCarpeta);

            foreach (IEntidadLinqAsociacionJerarquiaPadreHijo asociacion in jerarquiaCarpeta.AsociacionesJerarquiasHijos)
            {
                if (asociacion.JerarquiaHijo.Nombre == "Otros")
                {
                    return asociacion.JerarquiaHijo.Id;
                }
            }
            return new Guid();
        }

        /// <summary>
        /// Retorna el Id del candidato por un id de estacion
        /// </summary>
        /// <param name="idEstacion">Id de la estación</param>
        /// <returns>Id del candidato</returns>
        public string GetIdCandidatoByIdEstacion(string idEstacion)
        {
            return _contexto.GetIdCandidatoByIdEstacion(idEstacion);
        }


        /// <summary>
        /// Retorna el id de la carpeta otros segun un nombre de carpeta base y un id del candidato
        /// </summary>
        /// <param name="nombreCarpetaBase">nombre de la carpeta base</param>
        /// <param name="idCandidato">id del candidato</param>
        /// <returns>Id de la carpeta otros</returns>
        public Guid GetIdCarpetaOtros(string nombreCarpetaBase, Guid idCandidato)
        {
            IEntidadLinqJerarquiaCarpeta jerarquiaBase = _contexto.GetJerarquiByIdCandidatoNombreCarpeta(nombreCarpetaBase, idCandidato);
            foreach (IEntidadLinqAsociacionJerarquiaPadreHijo asociacion in jerarquiaBase.AsociacionesJerarquiasPadres)
            {
                if (asociacion.JerarquiaPadre.Nombre == (nombreCarpetaBase + "Otros"))
                {
                    return asociacion.JerarquiaPadre.Id;
                }
            }
            return new Guid();
        }


        /// <summary>
        /// Obtiene las carpetas hijas de una carpeta base
        /// </summary>
        /// <param name="nombreCarpetaBase">Nombre de la carpeta base</param>
        /// <returns></returns>
        public List<InfoJerarquia> GetDataSourceCarpetasHijas(string nombreCarpetaBase)
        {
            ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> jerarquias = _contexto.GetJerarquisHijasByJerarquiBaseName(nombreCarpetaBase);
            List<InfoJerarquia> resultado = new List<InfoJerarquia>();

            foreach (IEntidadLinqJerarquiaCarpeta carpeta in jerarquias)
            {
                string textoBoton = string.Empty;
                if (carpeta.Nombre.StartsWith(nombreCarpetaBase))
                {
                    textoBoton = carpeta.Nombre.Remove(0, nombreCarpetaBase.Length);
                }
                else
                {
                    textoBoton = carpeta.Nombre;
                }
                resultado.Add(new InfoJerarquia(carpeta.Nombre, textoBoton, carpeta.Id.ToString()));
            }
            return resultado;
        }

        /// <summary>
        /// Obtiene las carpetas hijas de una carpeta base. Sobrecarga que ademas filtra dependiendo
        /// de los roles de visibilidad de carpeta que se ingresen
        /// </summary>
        /// <param name="nombreCarpetaBase">nombre de la carpeta base</param>
        /// <param name="idRolesCarpetas">roles de carpetas a filtrar</param>
        /// <returns></returns>
        public List<InfoJerarquia> GetDataSourceCarpetasHijas(string nombreCarpetaBase, List<Guid> idRolesCarpetas)
        {
            ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> jerarquias = _contexto.GetJerarquisHijasByJerarquiBaseName(nombreCarpetaBase);
            List<InfoJerarquia> resultado = new List<InfoJerarquia>();

            foreach (IEntidadLinqJerarquiaCarpeta carpeta in jerarquias)
            {
                string textoBoton = string.Empty;
                if (carpeta.Nombre.StartsWith(nombreCarpetaBase))
                {
                    textoBoton = carpeta.Nombre.Remove(0, nombreCarpetaBase.Length);
                }
                else
                {
                    textoBoton = carpeta.Nombre;
                }
                //se filtran las carpetas viendo el listado de roles
                if (idRolesCarpetas.Contains(carpeta.Id))
                    resultado.Add(new InfoJerarquia(carpeta.Nombre, textoBoton, carpeta.Id.ToString()));
            }
            return resultado;

        }


        /// <summary>
        /// Obtiene las carpetas hijas de una carpeta base. Si se encuentra mas de una carpeta
        /// con el mismo nombre se obtendrán las hijas del primer padre que se encuentre.
        /// </summary>
        /// <param name="nombreCarpetaBase">Nombre de la carpeta base</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> GetDataSourceReadOnlyCollectionCarpetasHijas(string nombreCarpetaBase)
        {
            return _contexto.GetJerarquisHijasByJerarquiBaseName(nombreCarpetaBase);
        }

        /// <summary>
        /// Indica si el boton de aprobar un estado puede visualizarse o no dependiendo el rol del usuario
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoSeleccionado">Identificador del estado seleccionado</param>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="roles">Listado de los roles que tiene el usuario</param>
        /// <returns>Retorna si se puede o no visualizar el boton</returns>
        public bool VisibilidadEstadoAprobacion(Guid idProyecto, Guid idEstadoSeleccionado, Guid idDocumento, ReadOnlyCollection<string> roles)
        {
            //Se obtiene  el id del cliente y los estados del documento
            IEntidadLinqProyecto proyecto = _contexto.GetProyectoPorID(idProyecto);
            string idClienteTemporal = proyecto.IdCliente.ToString();
            string rol = string.Empty;

            List<InfoEstadosDocumentosProyecto> estados = GetDataSourceEstadosDocumentosProyecto(idProyecto.ToString(), idDocumento.ToString());

            // Se evalua si el documento esta en el estado Ninguno o en el estado creado y se forma el nombre del rol 

            Guid? idNinguno = _contexto.GetIdEstadoByNombre("Ninguno");
            if (idNinguno.HasValue)
            {
                if (idNinguno.Value == idEstadoSeleccionado)
                {
                    return false;
                }
            }

            Guid? idCreado = _contexto.GetIdEstadoByNombre("Creado");
            if (idCreado.HasValue)
            {
                if (idCreado.Value == idEstadoSeleccionado)
                {
                    InfoEstadosDocumentosProyecto estadoRol = GetPrimerEstado(estados);
                    if (estadoRol != null)
                    {
                        rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estadoRol.IdEstadoAprobado + "_" + estadoRol.IdEstadoRechazado;
                    }
                }
            }

            //Si no es ninguno de esos dos estados se busca si se esta en un estado aprobado o en un estado rechazado y se forma el nombre del rol

            if (rol == string.Empty)
            {
                InfoEstadosDocumentosProyecto estado = estados.Find(x => x.IdEstadoAprobado == idEstadoSeleccionado.ToString());
                if (estado == null)
                {
                    estado = estados.Find(x => x.IdEstadoRechazado == idEstadoSeleccionado.ToString());
                    if (estado != null)
                    {
                        //El estado actual es un estado rechazado
                        InfoEstadosDocumentosProyecto estadoSiguiente = GetEstadoSiguiente(estados, idEstadoSeleccionado.ToString(), false);
                        //Se mira si hay un estado siguiente si no se evalua si tiene el rol creador
                        //Si existe se crea el nombre del rol
                        if (estadoSiguiente == null)
                        {
                            rol = "Creador";

                        }
                        else
                        {
                            rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estadoSiguiente.IdEstadoAprobado + "_" + estadoSiguiente.IdEstadoRechazado;
                        }
                    }
                }
                else
                {
                    //El estado actual es un estado aprobado
                    InfoEstadosDocumentosProyecto estadoSiguiente = GetEstadoSiguiente(estados, idEstadoSeleccionado.ToString(), true);
                    //Se mira si hay un estado siguiente si no no se debe mostrar la aprobación
                    //Si existe se crea el nombre del rol
                    if (estadoSiguiente == null)
                    {
                        return false;
                    }
                    else
                    {
                        rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estadoSiguiente.IdEstadoAprobado + "_" + estadoSiguiente.IdEstadoRechazado;
                    }
                }

            }
            //Se evalua si el usuario tiene  el rol que puede hacer esta accion
            if (roles.Contains(rol))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Indica si el boton de rechazar un estado puede visualizarse o no dependiendo el rol del usuario
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoSeleccionado">Identificador del estado seleccionado</param>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="roles">Listado de los roles que tiene el usuario</param>
        /// <returns>Retorna si se puede o no visualizar el boton</returns>
        public bool VisibilidadEstadoRechazo(Guid idProyecto, Guid idEstadoSeleccionado, Guid idDocumento, ReadOnlyCollection<string> roles)
        {
            //Se obtiene  el id del cliente y los estados del documento
            IEntidadLinqProyecto proyecto = _contexto.GetProyectoPorID(idProyecto);
            string idClienteTemporal = proyecto.IdCliente.ToString();
            string rol = string.Empty;

            List<InfoEstadosDocumentosProyecto> estados = GetDataSourceEstadosDocumentosProyecto(idProyecto.ToString(), idDocumento.ToString());

            // Se evalua si el documento esta en el estado Ninguno o en el estado creado y se forma el nombre del rol 

            Guid? idNinguno = _contexto.GetIdEstadoByNombre("Ninguno");
            if (idNinguno.HasValue)
            {
                if (idNinguno.Value == idEstadoSeleccionado)
                {
                    return false;
                }
            }

            Guid? idCreado = _contexto.GetIdEstadoByNombre("Creado");
            if (idCreado.HasValue)
            {
                if (idCreado.Value == idEstadoSeleccionado)
                {
                    InfoEstadosDocumentosProyecto estadoRol = GetPrimerEstado(estados);
                    if (estadoRol != null)
                    {
                        rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estadoRol.IdEstadoAprobado + "_" + estadoRol.IdEstadoRechazado;
                    }
                }
            }

            //Si no es ninguno de esos dos estados se busca si se esta en un estado aprobado o en un estado rechazado y se forma el nombre del rol

            if (rol == string.Empty)
            {
                InfoEstadosDocumentosProyecto estado = estados.Find(x => x.IdEstadoAprobado == idEstadoSeleccionado.ToString());
                if (estado == null)
                {
                    estado = estados.Find(x => x.IdEstadoRechazado == idEstadoSeleccionado.ToString());
                    if (estado != null)
                    {
                        //El estado actual es un estado rechazado
                        InfoEstadosDocumentosProyecto estadoSiguiente = GetEstadoSiguiente(estados, idEstadoSeleccionado.ToString(), false);
                        //Se mira si hay un estado siguiente si no se mira el mismo rol de este estado para mostrar el rechazar;
                        //Si existe se crea el nombre del rol
                        if (estadoSiguiente == null)
                        {
                            rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estado.IdEstadoAprobado + "_" + estado.IdEstadoRechazado;
                        }
                        else
                        {
                            rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estadoSiguiente.IdEstadoAprobado + "_" + estadoSiguiente.IdEstadoRechazado;
                        }
                    }
                }
                else
                {
                    //El estado actual es un estado aprobado
                    InfoEstadosDocumentosProyecto estadoSiguiente = GetEstadoSiguiente(estados, idEstadoSeleccionado.ToString(), true);
                    //Se mira si hay un estado siguiente si no no se debe mostrar la aprobación
                    //Si existe se crea el nombre del rol
                    if (estadoSiguiente == null)
                    {
                        return false;
                    }
                    else
                    {
                        rol = "Rol_Estado_" + idClienteTemporal + "_" + idProyecto.ToString() + "_" + estadoSiguiente.IdEstadoAprobado + "_" + estadoSiguiente.IdEstadoRechazado;
                    }
                }

            }
            //Se evalua si el usuario tiene  el rol que puede hacer esta accion
            if (roles.Contains(rol))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// Obtiene el primer estado del documento
        /// </summary>
        /// <param name="estados">Datasource del cocumento</param>
        /// <returns>Retorna el primer estado o null si el documento no tiene estados</returns>
        private InfoEstadosDocumentosProyecto GetPrimerEstado(List<InfoEstadosDocumentosProyecto> estados)
        {
            for (int i = 0; i < estados.Count; i++)
            {
                if (estados[i].Seleccionado)
                {
                    return estados[i];
                }

            }
            return null;
        }

        /// <summary>
        /// Obtiene el siguiente estado de un documento en un flujo
        /// </summary>
        /// <param name="estados"></param>
        /// <param name="idEstado"></param>
        /// <param name="orden"></param>
        /// <returns></returns>
        private InfoEstadosDocumentosProyecto GetEstadoSiguiente(List<InfoEstadosDocumentosProyecto> estados, string idEstado, bool orden)
        {
            bool estadoEncontrado = false;
            if (orden)
            {
                for (int i = 0; i < estados.Count; i++)
                {
                    if (!estadoEncontrado)
                    {
                        if (estados[i].Seleccionado && ((estados[i].IdEstadoAprobado == idEstado) || (estados[i].IdEstadoRechazado == idEstado)))
                        {
                            estadoEncontrado = true;
                        }
                    }
                    else
                    {
                        if (estados[i].Seleccionado)
                        {
                            return estados[i];
                        }
                    }
                }
            }
            else
            {
                for (int i = estados.Count - 1; i >= 0; i--)
                {
                    if (!estadoEncontrado)
                    {
                        if (estados[i].Seleccionado && ((estados[i].IdEstadoAprobado == idEstado) || (estados[i].IdEstadoRechazado == idEstado)))
                        {
                            estadoEncontrado = true;
                        }
                    }
                    else
                    {
                        if (estados[i].Seleccionado)
                        {
                            return estados[i];
                        }
                    }
                }
            }
            return null;
        }



        /// <summary>
        /// Obtiene las carpetas hijas de una carpeta base
        /// </summary>
        /// <param name="idCarpetaBase">id de la carpeta base</param>
        /// <returns></returns>
        public ReadOnlyCollection<IEntidadLinqJerarquiaCarpeta> GetDataSourceReadOnlyCollectionCarpetasHijas(Guid idCarpetaBase)
        {
            return _contexto.GetJerarquisHijasByJerarquiBaseName(idCarpetaBase);
        }

        /// <summary>
        /// Inserta estados a un proyecto especifico
        /// </summary>
        /// <param name="idProyecto">id del proyecto al que pertenece ese estado</param>
        /// <param name="nombreEstado">nombre del estado</param>
        public void InsertarEstadoProyecto(Guid idProyecto, string nombreEstado)
        {
            _contexto.InsertarEstadoProyecto(idProyecto, nombreEstado);
        }

        /// <summary>
        /// Cambia un posible estado del documento
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        /// <param name="seleccionado">Dice si esta o no seleccionado como posible estado</param>
        public void CambiarPosibleEstadoDocumento(string idProyecto, string idDocumento, string idEstadoAprobado, string idEstadoRechazado, bool seleccionado)
        {
            if (seleccionado)
            {
                //_contexto.AsociarEstadoPosibleDocumento(new Guid(idDocumento), new Guid(idEstadoAprobado), new Guid(idEstadoRechazado));
                _contexto.AsociarEstadosDocumentosProyecto(new Guid(idProyecto), new Guid(idDocumento), new Guid(idEstadoAprobado), new Guid(idEstadoRechazado), true);
            }
            else
            {
                //_contexto.DesasociarEstadoPosibleDocumento(new Guid(idDocumento), new Guid(idEstadoAprobado), new Guid(idEstadoRechazado));
                _contexto.AsociarEstadosDocumentosProyecto(new Guid(idProyecto), new Guid(idDocumento), new Guid(idEstadoAprobado), new Guid(idEstadoRechazado), false);
            }


            _contexto.SubmitChanges();
        }

        /// <summary>
        /// Inserta estados de documentos a un proyecto en especifico
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="nombreEstadoAprobado">Nombre del estado de aprobado</param>
        /// <param name="nombreEstadoRechazado">Nombre del estado de rechazado</param>
        public void InsertarEstadoDocumentosProyecto(Guid idProyecto, string nombreEstadoAprobado, string nombreEstadoRechazado)
        {
            _contexto.InsertarEstadoDocumentosProyecto(idProyecto, nombreEstadoAprobado, nombreEstadoRechazado);
            //throw new NotImplementedException();
        }

        /// <summary>
        /// Metodo que asocia los estados predeterminados de ninguno y creado a un proyecto
        /// </summary>
        /// <param name="idProyecto"></param>
        public void InicializarAsociacionesEstadosPredeterminados(Guid idProyecto)
        {
            _contexto.InicializarAsociacionesEstadosPredeterminados(idProyecto);
        }


        /// <summary>
        /// Elimina un estado asociado a un proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idEstado">id del estado</param>
        public void BorrarEstadoProyecto(string idProyecto, string idEstado)
        {
            _contexto.BorrarEstadoProyecto(idProyecto, idEstado);
        }

        /// <summary>
        /// Elimina un estado de un documento
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoAprobado">Identificador del Estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void BorrarEstadoDocumentosProyecto(string idProyecto, string idEstadoAprobado, string idEstadoRechazado)
        {
            _contexto.BorrarEstadoDocumentosProyecto(idProyecto, idEstadoAprobado, idEstadoRechazado);
        }


        /// <summary>
        /// Obtiene una lista con la informacion de los estados del proyecto
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <returns></returns>
        public List<InfoEstadosProyecto> GetDataSourceEstadosProyecto(string idProyecto)
        {
            ReadOnlyCollection<IEntidadLinqAsociacionProyectosEstadoProyecto> asociaciones = _contexto.GetAsociacionesEstadoProyectosByIdProyecto(idProyecto);
            List<InfoEstadosProyecto> resultado = new List<InfoEstadosProyecto>();

            foreach (IEntidadLinqAsociacionProyectosEstadoProyecto asociacion in asociaciones)
            {
                resultado.Add(new InfoEstadosProyecto(asociacion.IdProyecto.ToString(), asociacion.IdEstadoProyecto.ToString(), asociacion.EstadoProyectoAsociado.Nombre, asociacion.Consecutivo, this));
            }
            return resultado;
        }

        /// <summary>
        /// Obtiene una lista con la informacion de los estados de los documentos de un proyecto
        /// </summary>
        /// <param name="idProyecto">Identicicador del proyecto</param>
        /// <returns></returns>
        public List<InfoEstadosDocumentosProyecto> GetDataSourceEstadosDocumentosProyecto(string idProyecto)
        {
            ReadOnlyCollection<IEntidadLinqAsociacionProyectosEstadoDocumentos> asociaciones = _contexto.GetAsociacionesEstadoDocumentosProyectosByIdProyecto(idProyecto);
            List<InfoEstadosDocumentosProyecto> resultado = new List<InfoEstadosDocumentosProyecto>();
            InfoEstadosDocumentosProyecto estadoAdicionado;
            string idEstadoRechazado = string.Empty;
            string nombreEstadoRechazado = string.Empty;
            int consecutivoEstadoRechazado = 0;
            for (int i = 0; i < asociaciones.Count; i++) //(IEntidadLinqAsociacionProyectosEstadoDocumentos asociacion in asociaciones)
            {
                if (asociaciones[i].Consecutivo > 1)
                {
                    //Aca se saca el estado rechazado
                    if ((asociaciones[i].Consecutivo % 2) == 0)
                    {
                        idEstadoRechazado = asociaciones[i].IdEstadoDocumento.ToString();
                        nombreEstadoRechazado = asociaciones[i].EstadoDocumentoAsociado.Nombre;
                        consecutivoEstadoRechazado = asociaciones[i].Consecutivo;

                    }
                    //Aca se crea el estado de aprobado y se insertan los dos estados en la clase de informacion de los estados
                    else
                    {
                        estadoAdicionado = new InfoEstadosDocumentosProyecto(idProyecto,
                            asociaciones[i].IdEstadoDocumento.ToString(),
                            asociaciones[i].EstadoDocumentoAsociado.Nombre,
                            asociaciones[i].Consecutivo,
                            idEstadoRechazado,
                            nombreEstadoRechazado,
                            consecutivoEstadoRechazado,
                            this);
                        resultado.Add(estadoAdicionado);
                    }
                }
            }
            return resultado;
        }

        /// <summary>
        /// Obtiene una lista con la informacion de los estados de los documentos de un proyecto
        /// </summary>
        /// <param name="idProyecto">Identicicador del proyecto</param>
        /// <param name="idDocumento">Identificador del documento</param>
        /// <returns></returns>
        public List<InfoEstadosDocumentosProyecto> GetDataSourceEstadosDocumentosProyecto(string idProyecto, string idDocumento)
        {
            ReadOnlyCollection<IEntidadLinqAsociacionProyectosEstadoDocumentos> asociaciones = _contexto.GetAsociacionesEstadoDocumentosProyectosByIdProyecto(idProyecto);
            List<InfoEstadosDocumentosProyecto> resultado = new List<InfoEstadosDocumentosProyecto>();
            InfoEstadosDocumentosProyecto estadoAdicionado;
            string idEstadoRechazado = string.Empty;
            string nombreEstadoRechazado = string.Empty;
            int consecutivoEstadoRechazado = 0;
            for (int i = 0; i < asociaciones.Count; i++) //(IEntidadLinqAsociacionProyectosEstadoDocumentos asociacion in asociaciones)
            {
                if (asociaciones[i].Consecutivo > 1)
                {
                    //Aca se saca el estado rechazado
                    if ((asociaciones[i].Consecutivo % 2) == 0)
                    {
                        idEstadoRechazado = asociaciones[i].IdEstadoDocumento.ToString();
                        nombreEstadoRechazado = asociaciones[i].EstadoDocumentoAsociado.Nombre;
                        consecutivoEstadoRechazado = asociaciones[i].Consecutivo;

                    }
                    //Aca se crea el estado de aprobado y se insertan los dos estados en la clase de informacion de los estados
                    else
                    {
                        bool seleccionado = _contexto.ExistenAsociaciones(new Guid(idDocumento), asociaciones[i].IdEstadoDocumento, new Guid(idEstadoRechazado));
                        estadoAdicionado = new InfoEstadosDocumentosProyecto(idProyecto, idDocumento,
                            asociaciones[i].IdEstadoDocumento.ToString(),
                            asociaciones[i].EstadoDocumentoAsociado.Nombre,
                            asociaciones[i].Consecutivo,
                            idEstadoRechazado,
                            nombreEstadoRechazado,
                            consecutivoEstadoRechazado,
                            seleccionado,
                            this);
                        resultado.Add(estadoAdicionado);
                    }
                }
            }
            return resultado;
        }


        /// <summary>
        /// Indica si el boton de bajar el orden del estado se puede ver
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idEstado">id del estado</param>
        /// <returns></returns>
        public bool VisivilidadBotonDownEstado(string idProyecto, string idEstado)
        {
            return _contexto.UltimoEstadoProyecto(idProyecto, idEstado);
        }

        /// <summary>
        /// Indica si el boton de bajar el orden del estado del documento se puede ver
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idEstadoAprobado">id del estado de aprobacion</param>
        /// <returns></returns>
        public bool VisivilidadBotonDownEstadoDocumento(string idProyecto, string idEstadoAprobado)
        {
            return _contexto.UltimoEstadoDocumentoProyecto(idProyecto, idEstadoAprobado);
        }

        /// <summary>
        /// Sube el orden del estado del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstado">Identificador del estado</param>
        public void SubirOrdenEstadoProyecto(string idProyecto, string idEstado)
        {
            _contexto.SubirOrdenEstadoProyecto(new Guid(idProyecto), new Guid(idEstado));
        }

        /// <summary>
        /// Baja el orden del estado del proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstado">Identificador del estado</param>
        public void BajarOrdenEstadoProyecto(string idProyecto, string idEstado)
        {
            _contexto.BajarOrdenEstadoProyecto(new Guid(idProyecto), new Guid(idEstado));
        }


        /// <summary>
        /// Obtiene el Id de una carpeta hija por el nombre de la carpeta
        /// </summary>
        /// <param name="idCarpeta">id de la carpeta en donde se va a buscar</param>
        /// <param name="nombreCarpeta">nombre de la carpeta que se va a buscar</param>
        /// <returns>Id de la carpeta hija</returns>
        public Guid GetIdCarpetaHijaByName(Guid idCarpeta, string nombreCarpeta)
        {
            IEntidadLinqJerarquiaCarpeta jerarquiaCarpeta = _contexto.GetJerarquiaById(idCarpeta);
            if (jerarquiaCarpeta != null)
            {

                foreach (IEntidadLinqAsociacionJerarquiaPadreHijo asociacion in jerarquiaCarpeta.AsociacionesJerarquiasHijos)
                {
                    if (asociacion.JerarquiaHijo.Nombre == nombreCarpeta)
                    {
                        return asociacion.JerarquiaHijo.Id;
                    }
                }
            }
            return new Guid();
        }

        /// <summary>
        /// Obtiene el Id de una carpeta con el nombre de la carpeta. Si existe varias carpetas
        /// con el mismo nombre retornara el primer id que encuentre.
        /// </summary>
        /// <param name="nombreCarpeta">nombre de la carpeta que se va a buscar</param>
        /// <returns>Id de la carpeta</returns>
        public Guid GetIdCarpetaByName(string nombreCarpeta)
        {
            return _contexto.GetIdJerarquiaByNombre(nombreCarpeta);
        }





        private ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosByCandidato(Guid idCandidato)
        {
            List<IEntidadLinqDocumento> resultado = new List<IEntidadLinqDocumento>();
            ReadOnlyCollection<IEntidadLinqDocumento> tx = _contexto.GetDocumentosByCandidatoCategoria(idCandidato, "TxBase");
            ReadOnlyCollection<IEntidadLinqDocumento> rf = _contexto.GetDocumentosByCandidatoCategoria(idCandidato, "RfBase");
            ReadOnlyCollection<IEntidadLinqDocumento> infra = _contexto.GetDocumentosByCandidatoCategoria(idCandidato, "InfraestructuraBase");
            ReadOnlyCollection<IEntidadLinqDocumento> legal = _contexto.GetDocumentosByCandidatoCategoria(idCandidato, "LegalBase");

            resultado.AddRange(tx.AsEnumerable<IEntidadLinqDocumento>());
            resultado.AddRange(rf.AsEnumerable<IEntidadLinqDocumento>());
            resultado.AddRange(infra.AsEnumerable<IEntidadLinqDocumento>());
            resultado.AddRange(legal.AsEnumerable<IEntidadLinqDocumento>());
            return resultado.AsReadOnly();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentosReporte()
        {
            return null;//_contexto.GetDocumentosReporte();
        }


        /// <summary>
        /// Retorna un DataSource de los documentos permitidos para la carpeta indicada
        /// </summary>
        /// <param name="idCarpeta">Id de la carpeta a buscar</param>
        /// <returns>DataSource para un Repeater</returns>
        public Object GetDataSourceDocumentosRoles(Guid idCarpeta)
        {
            return _contexto.GetDocumentosByJerarquiaId(idCarpeta);
        }

        /// <summary>
        /// Busca un documento por un id especifico
        /// </summary>
        /// <param name="idDocumento">ID del documento a buscar</param>
        /// <returns>Retorna el documento  o null si no existe un documento con ese id</returns>
        public IEntidadLinqDocumento GetDocumentoById(Guid idDocumento)
        {
            return _contexto.GetDocumentoById(idDocumento);
        }

        /// <summary>
        /// Busca un documento por un id especifico de proyecto
        /// </summary>
        /// <param name="idProyecto">ID del proyecto a buscar</param>
        /// <returns>Retorna el documento  o null si no existe un documento con ese id</returns>
        public ReadOnlyCollection<IEntidadLinqDocumento> GetDocumentoByIdProyecto(Guid idProyecto)
        {
            return _contexto.GetDocumentosByIdProyecto(idProyecto);
        }




        /// <summary>
        /// Retorna un DataSource de clientes
        /// </summary>
        /// <param name="idCliente">Identificador del cliente</param>
        /// <returns>DataSource de Clientes</returns>
        public ILinqDataSource GetDataSourceClientes(string idCliente)
        {
            ILinqDataSource dataSourceClientes = _fabricaLinqDataSource.Construir();
            dataSourceClientes.TableName = _nombreEntidadCliente;
            if (idCliente != string.Empty)
                dataSourceClientes.Where = "Id == Guid(\"" + idCliente + "\")";
            dataSourceClientes.EnableViewState = true;
            return dataSourceClientes;
        }


        /// <summary>
        /// Se crea un reporte de documentos con el ID del proyecto
        /// </summary>
        /// <param name="reporte">Stream donde se va a generar el reporte</param>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="costos">Indica si el proyecto es de costos o no</param>
        // /// <returns>Retorna stream del reporte</returns>
        public void CrearReporteDocumentosByProyecto(MemoryStream reporte, Guid idProyecto, bool costos)
        {
            //Se crea un Text writer para generar el archivo

            //Se crea un memory stream donde se 
            //MemoryStream reporte = new MemoryStream();
            TextWriter writer = new StreamWriter(reporte);

            //Se obtienen los documentos del proyecto
            ReadOnlyCollection<IEntidadLinqDocumento> documentos = _contexto.GetDocumentosReporte(idProyecto);

            //Se escriben las cabeceras del reporte
            #region CABECERAS DEL ARCHIVO
            Guid idCandidato = ((Documento)documentos[0]).AsociacionCandidatoDocumento.idCandidato;
            string cadenaTexto = string.Empty;
            int i = 0;
            cadenaTexto += "SITIO,CANDIDATO";
            if (!costos)
            {
                while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
                {
                    cadenaTexto += ",FECHA PLANEADA," + ((Documento)documentos[i]).DocumentoTag.Nombre;
                    i++;
                }
            }
            else
            {
                while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
                {
                    cadenaTexto += "," + ((Documento)documentos[i]).DocumentoTag.Nombre;
                    i++;
                }
                cadenaTexto += ",TOTAL";
            }
            writer.WriteLine(cadenaTexto);
            #endregion

            //Se llena el archivo con la informacion de los documentos
            #region INFORMACION DEL ARCHIVO
            for (i = 0; i < documentos.Count; i++)
            {
                string linea = string.Empty;
                string vacio = "---";
                string fecha = string.Empty;
                idCandidato = ((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato;
                linea += ((Documento)documentos[i]).AsociacionCandidatoDocumento.Candidato.Sitio.Nombre.Trim() + "," +
                             ((Documento)documentos[i]).AsociacionCandidatoDocumento.Candidato.Nombre.Trim();
                if (!costos)
                {
                   
                    while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
                    {
                        if (documentos[i].Estado == "Ninguno")
                        {
                            fecha = vacio;
                        }
                        else
                        {
                            fecha = ((Documento)documentos[i]).Fecha.ToShortDateString() + "-" + ((Documento)documentos[i]).Estado;
                        }

                        linea += ",," + fecha;
                        i++;
                        if (i == documentos.Count)
                            break;
                    }
                    i--;
                }
                else
                {
                    string costo = string.Empty;
                    double costoTotal = 0;
                    while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
                    {
                        if (documentos[i].Facturable == false)
                        {
                            costo = "NA";
                        }
                        else
                        {
                            if (documentos[i].Estado == "Ninguno")
                            {
                                fecha = vacio;
                            }
                            else
                            {
                                costo = "OK";
                                if (((Documento)(documentos[i])).DocumentoTag.Costo.HasValue)
                                {
                                    costoTotal += ((Documento)(documentos[i])).DocumentoTag.Costo.Value;
                                }
                            }
                        }

                        linea += "," + costo;
                        i++;

                        if (i == documentos.Count)
                            break;
                    }
                    i--;
                    linea += "," + costoTotal.ToString();

                }
           

                writer.WriteLine(linea);
            }
            #endregion
          
            writer.Close();
        }




        /// <summary>
        /// Crea el reporte de documentos
        /// </summary>
        /// <param name="filename">nombre del archivo a crear</param>
        public void CrearReporteDocumentos(string filename)
        {

            TextWriter writer = new StreamWriter(filename);
            ReadOnlyCollection<IEntidadLinqDocumento> documentos = GetDocumentosReporte();

            Guid idCandidato = ((Documento)documentos[0]).AsociacionCandidatoDocumento.idCandidato;
            string cadenaTexto = string.Empty;
            cadenaTexto += "SITIO,CANDIDATO";
            int i = 0;
            while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
            {
                cadenaTexto += ",FECHA PLANEADA," + ((Documento)documentos[i]).DocumentoTag.Nombre;
                i++;
            }
            writer.WriteLine(cadenaTexto);

            for (i = 0; i < documentos.Count; i++)
            {
                string linea = string.Empty;
                string fecha;
                string vacio = "---";
                idCandidato = ((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato;


                linea += ((Documento)documentos[i]).AsociacionCandidatoDocumento.Candidato.Sitio.Nombre.Trim() + "," +
                         ((Documento)documentos[i]).AsociacionCandidatoDocumento.Candidato.Nombre.Trim();
                while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
                {
                    if (documentos[i].Estado == "Ninguno")
                    {
                        fecha = vacio;
                    }
                    else
                    {
                        fecha = ((Documento)documentos[i]).Fecha.ToShortDateString() + "-" + ((Documento)documentos[i]).Estado;
                    }

                    linea += ",," + fecha;
                    i++;
                    if (i == documentos.Count)
                        break;
                }
                i--;
                writer.WriteLine(linea);


            }
            writer.Close();
        }

        /// <summary>
        /// Crea el reporte de costos
        /// </summary>
        /// <param name="filename">nombre del archivo a crear</param>
        public void CrearReporteCostos(string filename)
        {
            TextWriter writer = new StreamWriter(filename);
            ReadOnlyCollection<IEntidadLinqDocumento> documentos = GetDocumentosReporte();

            Guid idCandidato = ((Documento)documentos[0]).AsociacionCandidatoDocumento.idCandidato;
            string cadenaTexto = string.Empty;
            cadenaTexto += "SITIO,CANDIDATO";
            int i = 0;
            while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
            {
                cadenaTexto += "," + ((Documento)documentos[i]).DocumentoTag.Nombre;
                i++;
            }
            cadenaTexto += ",TOTAL";

            writer.WriteLine(cadenaTexto);
            for (i = 0; i < documentos.Count; i++)
            {
                string linea = string.Empty;
                string costo;
                string vacio = "---";
                idCandidato = ((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato;


                linea += ((Documento)documentos[i]).AsociacionCandidatoDocumento.Candidato.Sitio.Nombre.Trim() + "," +
                         ((Documento)documentos[i]).AsociacionCandidatoDocumento.Candidato.Nombre.Trim();
                double costoTotal = 0;
                while (((Documento)documentos[i]).AsociacionCandidatoDocumento.idCandidato == idCandidato)
                {
                    if (documentos[i].Facturable == false)
                    {
                        costo = "NA";
                    }
                    else
                    {
                        if (documentos[i].Estado != "Ninguno")
                        {
                            costo = vacio;
                        }
                        else
                        {
                            costo = "OK";
                            if (((Documento)(documentos[i])).DocumentoTag.Costo.HasValue)
                            {
                                costoTotal += ((Documento)(documentos[i])).DocumentoTag.Costo.Value;
                            }
                        }
                    }

                    linea += "," + costo;
                    i++;

                    if (i == documentos.Count)
                        break;
                }
                i--;
                linea += "," + costoTotal.ToString();
                writer.WriteLine(linea);
            }
            writer.Close();
        }



        /// <summary>
        /// Retorna un DataSource de Carpetas para el Candidato indicado
        /// </summary>
        /// <param name="idCandidato">Identificador Candidato</param>
        /// <param name="fabricaDataSourceTreeView">Fabrica de dataSOurce para el TreeView</param>
        /// <returns>DataSource Carpetas</returns>
        public IJerarquiaCarpetaDataSource GetDataSourceTreeView(Guid idCandidato, IFabricaJerarquiaCarpetaDataSource fabricaDataSourceTreeView)
        {
            List<IEntidadLinqCandidato> candidatos = _contexto.Candidatos.ToList();

            foreach (IEntidadLinqCandidato candidato in candidatos)
            {
                if (candidato.Id == idCandidato)
                {
                    //TODO arreglar 
                    //IEntidadLinqJerarquiaCarpeta jerarquiaCarpeta = candidato.EntidadJerarquiaCarpeta;
                    IJerarquiaCarpetaDataSource dataSourceTreeView = fabricaDataSourceTreeView.Construir();
                    //dataSourceTreeView.EntidadJerarquiaCarpeta = jerarquiaCarpeta;

                    return dataSourceTreeView;
                }
            }

            return null;
        }

        /// <summary>
        /// Retorna un DataSource de Documentos para la Carpeta indicada
        /// </summary>
        /// <param name="idCarpeta">Identificador de la Carpeta</param>
        /// <returns>DataSource Documentos</returns>
        public ILinqDataSource GetDataSourceDocumentos(Guid idCarpeta)
        {
            ILinqDataSource dataSourceDocumentos = _fabricaLinqDataSource.Construir();
            dataSourceDocumentos.TableName = _nombreEntidadDocumento;
            dataSourceDocumentos.Where = "IdJerarquiaCarpeta == Guid(\"" + idCarpeta.ToString() + "\")";
            dataSourceDocumentos.EnableViewState = true;
            return dataSourceDocumentos;
        }

        /// <summary>
        /// Carga un documento en el servidor
        /// </summary>
        /// <param name="nombreArchivo">Nombre del Documento</param>
        /// <param name="archivo">Arreglo de Bytes con la información del Documento</param>
        /// <param name="comentario">Comentario del documento</param>
        /// <param name="idJerarquiaCarpeta">Identificador JerarquiaCarpeta</param>
        /// <param name="fabricaDocumento">Fabrica de EntidadesDocumento</param>
        public void UploadDocumento(string nombreArchivo,
                                    System.Data.Linq.Binary archivo,
                                    string comentario,
                                    Guid idJerarquiaCarpeta,
                                    IFabricaObjetosLinqJerarquiaDocumentos fabricaDocumento)
        {
            IEntidadLinqDocumento documento = fabricaDocumento.ConstruirDocumento();
            documento.Id = Guid.NewGuid();
            documento.Nombre = nombreArchivo;
            documento.Descripcion = comentario;
            documento.Archivo = archivo;
            //documento.Tipo = nombreArchivo.Split(new char[1] { '.' }).Last();
            //TODOArreglar 
            //documento.IdJerarquiaCarpeta = idJerarquiaCarpeta;
            //  documento.IdEstadoDocumento = 0;
            documento.Fecha = DateTime.Now;
            _contexto.InsertarDocumento(documento);
            _contexto.SubmitChanges();
        }
        /// <summary>
        /// Carga un documento en el servidor
        /// </summary>
        /// <param name="nombreArchivo">Nombre del Documento</param>
        /// <param name="archivo">Arreglo de Bytes con la información del Documento</param>
        /// <param name="comentario">Comentario del documento</param>
        /// <param name="idJerarquiaCarpeta">Identificador JerarquiaCarpeta</param>
        /// <param name="fabricaDocumento">Fabrica de EntidadesDocumento</param>
        /// <param name="idProyecto">id del proyecto asociado</param>
        /// <param name="idDocumentoTag">id del tag asociado</param>
        public void UploadDocumento(string nombreArchivo,
                                              System.Data.Linq.Binary archivo,
                                              string comentario,
                                              Guid idJerarquiaCarpeta,
                                              IFabricaObjetosLinqJerarquiaDocumentos fabricaDocumento,
                                              Guid idProyecto,
                                              int idDocumentoTag)
        {
            IEntidadLinqDocumento documento = fabricaDocumento.ConstruirDocumento();
            documento.Id = Guid.NewGuid();
            documento.Nombre = nombreArchivo;
            documento.Descripcion = comentario;
            documento.Archivo = archivo;
            documento.IdJerarquiaCarpeta = idJerarquiaCarpeta;
            documento.IdProyecto = idProyecto;
            documento.IdDocumentoTag = idDocumentoTag;
            documento.IdEstadoDocumentoSeleccionado = _contexto.GetIdEstadoByNombre("Ninguno");

            documento.Fecha = DateTime.Now;
            _contexto.InsertarDocumento(documento);

            //Este metodo se usa para crear la asociacion de los estados ninguno y creado del documento
            _contexto.AsociarEstadoPosibleDocumento(documento.Id, _contexto.GetIdEstadoByNombre("Creado").Value, _contexto.GetIdEstadoByNombre("Ninguno").Value);

            _contexto.SubmitChanges();
        }
        /// <summary>
        /// Inserta el documento reporte
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="nombreArchivo">nombre del archivo</param>
        /// <param name="archivo">archivo</param>
        /// <param name="nombreCarpetaBase">nombre de la carpeta base</param>
        public void InsertarDocumentoReporte(Guid idProyecto, string nombreArchivo, System.Data.Linq.Binary archivo, string nombreCarpetaBase)
        {
            Guid idJerarquia = _contexto.GetIdJerarquiaByNombre(nombreCarpetaBase);
            if (idJerarquia == (new Guid()))
            {
                idJerarquia = _contexto.CrearJerarquiaCarpeta(nombreCarpetaBase);
            }

            _contexto.InsertarDocumentoReporte(idProyecto, nombreArchivo, archivo, idJerarquia);
        }

        /// <summary>
        /// Inserta una carpeta. Si existe alguna carpeta con el mismo nombre no se
        /// agrega nada
        /// </summary>
        /// <param name="nombreCarpeta">Nombre de la carpeta</param>
        /// <returns>id de la carpeta creada, es null si el nombre de carpeta ya esta siendo usado</returns>
        public Guid? InsertarCarpeta(string nombreCarpeta)
        {
            Guid idJerarquia = _contexto.GetIdJerarquiaByNombre(nombreCarpeta);
            if (idJerarquia == (new Guid()))
            {
                return _contexto.CrearJerarquiaCarpeta(nombreCarpeta);
            }
            else
                return null;
        }

        /// <summary>
        /// Obtiene una lista de candidatos por el nombre de un sitio
        /// </summary>
        /// <param name="nombreSitio">nombre o parte del nombre del sitio</param>
        /// <returns>Retorna un linq data source con los candidatos</returns>
        public ILinqDataSource GetDataSourceCandidatosByNombreSitio(string nombreSitio)
        {
            ILinqDataSource dataSourceCandidatos = _fabricaLinqDataSource.Construir();
            dataSourceCandidatos.TableName = _nombreEntidadCandidato;
            dataSourceCandidatos.Where = "NombreSitio.Contains(@Nombre)";
            dataSourceCandidatos.OrderBy = "NombreSitio, Nombre";
            dataSourceCandidatos.EnableViewState = true;
            return dataSourceCandidatos;
        }
        /// <summary>
        /// Carga un documento en el servidor
        /// </summary>
        /// <param name="nombreArchivo">Nombre del Documento</param>
        /// <param name="archivo">Arreglo de Bytes con la información del Documento</param>
        /// <param name="comentario">Comentarios del documento</param>
        /// <param name="idJerarquiaCarpeta">Identificador JerarquiaCarpeta</param>
        /// <param name="idCandidato">Id del candidato asociado al documento</param>
        public void UploadDocumento(string nombreArchivo,
                                    System.Data.Linq.Binary archivo,
                                    string comentario,
                                    Guid idJerarquiaCarpeta,
                                    Guid idCandidato)
        {
            Documento otroDocumento = new Documento();
            otroDocumento.Id = Guid.NewGuid();

            otroDocumento.Nombre = nombreArchivo;
            otroDocumento.Archivo = archivo;
            otroDocumento.Fecha = DateTime.Now;
            //  otroDocumento.IdEstadoDocumento = 1;
            otroDocumento.Descripcion = comentario;
            otroDocumento.JerarquiaCarpeta = (JerarquiaCarpeta)_contexto.GetJerarquiaById(idJerarquiaCarpeta);


            AsociacionCandidatoDocumento asociacion = new AsociacionCandidatoDocumento();
            asociacion.idCandidato = idCandidato;
            asociacion.idDocumento = otroDocumento.Id;
            _contexto.InsertarDocumento((IEntidadLinqDocumento)otroDocumento);
            _contexto.InsertarAsociacionDocumentoCandidato(asociacion);
            _contexto.SubmitChanges();
        }

        /// <summary>
        /// Carga un documento en el servidor
        /// </summary>
        /// <param name="nombreArchivo">Nombre del Documento</param>
        /// <param name="archivo">Arreglo de Bytes con la información del Documento</param>
        /// <param name="comentario">Comentarios del documento</param>
        /// <param name="idJerarquiaCarpeta">Identificador JerarquiaCarpeta</param>
        /// <param name="idCandidato">Id del candidato asociado al documento</param>
        /// <param name="idDocumentoTag">Id del tag del documento</param>
        /// <param name="idProyecto">Id del proyecto</param>
        public void UploadDocumento(string nombreArchivo,
                                              System.Data.Linq.Binary archivo,
                                              string comentario,
                                              Guid idJerarquiaCarpeta,
                                              Guid idCandidato,
                                              int idDocumentoTag,
                                              Guid idProyecto)
        {
            Documento otroDocumento = new Documento();
            otroDocumento.Id = Guid.NewGuid();

            otroDocumento.Nombre = nombreArchivo;
            otroDocumento.Archivo = archivo;
            otroDocumento.Fecha = DateTime.Now;
            //  otroDocumento.IdEstadoDocumento = 1;
            otroDocumento.Descripcion = comentario;
            otroDocumento.JerarquiaCarpeta = (JerarquiaCarpeta)_contexto.GetJerarquiaById(idJerarquiaCarpeta);
            otroDocumento.IdDocumentoTag = idDocumentoTag;
            otroDocumento.IdProyecto = idProyecto;
            otroDocumento.IdEstadoDocumentoSeleccionado = _contexto.GetIdEstadoByNombre("Ninguno");
            AsociacionCandidatoDocumento asociacion = new AsociacionCandidatoDocumento();
            asociacion.idCandidato = idCandidato;
            asociacion.idDocumento = otroDocumento.Id;
            _contexto.InsertarDocumento((IEntidadLinqDocumento)otroDocumento);
            _contexto.InsertarAsociacionDocumentoCandidato(asociacion);
            //Este metodo se usa para crear la asociacion de los estados ninguno y creado del documento
            _contexto.AsociarEstadoPosibleDocumento(otroDocumento.Id, _contexto.GetIdEstadoByNombre("Creado").Value, _contexto.GetIdEstadoByNombre("Ninguno").Value);
            _contexto.SubmitChanges();
        }
        /// <summary>
        /// Aplica los cambios en la base de datos y revisa conflictos
        /// </summary>
        public void AplicarCambios()
        {
            _contexto.SubmitChanges();
        }


        /// <summary>
        /// Aprueba un documento en el flujo de aprobación definido
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idDocumento">id de documento a aprobar</param>
        /// <param name="idEstado">id del estado actual del documento</param>
        public void AprobarDocumento(string idProyecto, string idDocumento, string idEstado)
        {
            List<InfoEstadosDocumentosProyecto> estados = GetDataSourceEstadosDocumentosProyecto(idProyecto, idDocumento);
            bool estadoAprobado = false;
            if (_contexto.EsEstadoCreado(idEstado))
            {
                for (int i = 0; i < estados.Count; i++)
                {
                    if (estados[i].Seleccionado)
                    {
                        _contexto.CambiarEstadoDocumento(idDocumento, estados[i].IdEstadoAprobado);
                        estadoAprobado = true;
                        break;
                    }
                }
            }
            else
            {
                bool estadoEncontrado = false;
                InfoEstadosDocumentosProyecto estado = estados.Find(x => x.IdEstadoAprobado == idEstado);
                if (estado != null)
                {
                    // Se va a aprobar desde un estado aprobado


                    //Se recorre en orden la lista de estados
                    for (int i = 0; i < estados.Count; i++)
                    {
                        //Se busca el estado actual
                        //Despues de encontrado el estado actual se busca el siguiente estado posible del documento para aprobarlo
                        if (!estadoEncontrado)
                        {
                            if (estados[i] == estado)
                            {
                                estadoEncontrado = true;
                            }
                        }
                        else
                        {
                            if (estados[i].Seleccionado)
                            {
                                if (estados[i].Seleccionado)
                                {
                                    _contexto.CambiarEstadoDocumento(idDocumento, estados[i].IdEstadoAprobado);
                                    estadoAprobado = true;
                                    break;
                                }
                            }

                        }
                    }
                }
                else
                {
                    estado = estados.Find(x => x.IdEstadoRechazado == idEstado);
                    // Se va a aprobar desde un estado rechazado
                    if (estado != null)
                    {
                        //Se recorre en orden descendente la lista de los estados
                        for (int i = estados.Count - 1; i >= 0; i--)
                        {
                            //Se busca el estado actual
                            //Despues de encontrado el estado actual se busca el siguiente estado posible del documento para aprobarlo
                            if (!estadoEncontrado)
                            {
                                if (estados[i] == estado)
                                {
                                    estadoEncontrado = true;
                                }
                            }
                            else
                            {
                                if (estados[i].Seleccionado)
                                {
                                    if (estados[i].Seleccionado)
                                    {
                                        _contexto.CambiarEstadoDocumento(idDocumento, estados[i].IdEstadoAprobado);
                                        estadoAprobado = true;
                                        break;
                                    }
                                }

                            }
                        }
                        //Si el estado no esta en la lista es porque es el primer estado y se debe pasar al estado creado
                        if (estadoAprobado == false)
                        {
                            CambiarDocumentoEstadoCreado(idDocumento);
                        }

                    }
                }
            }
        }
        /// <summary>
        /// Cambia un documento al estado creado
        /// </summary>
        /// <param name="idDocumento">Identificador del documento</param>
        public void CambiarDocumentoEstadoCreado(string idDocumento)
        {
            _contexto.CambiarDocumentoEstadoCreado(idDocumento);
        }

        /// <summary>
        /// Rechaza un documento en el flujo de aprobación definido
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idDocumento">id de documento a rechazar</param>
        /// <param name="idEstado">id del estado actual del documento</param>
        public void RechazarDocumento(string idProyecto, string idDocumento, string idEstado)
        {
            List<InfoEstadosDocumentosProyecto> estados = GetDataSourceEstadosDocumentosProyecto(idProyecto, idDocumento);
            bool estadoAprobado = false;
            if (_contexto.EsEstadoCreado(idEstado))
            {
                for (int i = 0; i < estados.Count; i++)
                {
                    if (estados[i].Seleccionado)
                    {
                        _contexto.CambiarEstadoDocumento(idDocumento, estados[i].IdEstadoRechazado);
                        estadoAprobado = true;
                        break;
                    }
                }
            }
            else
            {
                bool estadoEncontrado = false;
                InfoEstadosDocumentosProyecto estado = estados.Find(x => x.IdEstadoAprobado == idEstado);
                if (estado != null)
                {
                    // Se va a rechazar desde un estado aprobado


                    //Se recorre en orden la lista de estados
                    for (int i = 0; i < estados.Count; i++)
                    {
                        //Se busca el estado actual
                        //Despues de encontrado el estado actual se busca el siguiente estado posible del documento para rechazarlo
                        if (!estadoEncontrado)
                        {
                            if (estados[i] == estado)
                            {
                                estadoEncontrado = true;
                            }
                        }
                        else
                        {
                            if (estados[i].Seleccionado)
                            {
                                if (estados[i].Seleccionado)
                                {
                                    _contexto.CambiarEstadoDocumento(idDocumento, estados[i].IdEstadoRechazado);
                                    estadoAprobado = true;
                                    break;
                                }
                            }

                        }
                    }
                    if (!estadoAprobado)
                    {
                        _contexto.CambiarEstadoDocumento(idDocumento, estado.IdEstadoRechazado);
                    }
                }
                else
                {
                    estado = estados.Find(x => x.IdEstadoRechazado == idEstado);
                    // Se va a rechazar desde un estado rechazado
                    if (estado != null)
                    {
                        //Se recorre en orden descendente la lista de los estados
                        for (int i = estados.Count - 1; i >= 0; i--)
                        {
                            //Se busca el estado actual
                            //Despues de encontrado el estado actual se busca el siguiente estado posible del documento para aprobarlo
                            if (!estadoEncontrado)
                            {
                                if (estados[i] == estado)
                                {
                                    estadoEncontrado = true;
                                }
                            }
                            else
                            {
                                if (estados[i].Seleccionado)
                                {
                                    if (estados[i].Seleccionado)
                                    {
                                        _contexto.CambiarEstadoDocumento(idDocumento, estados[i].IdEstadoRechazado);
                                        estadoAprobado = true;
                                        break;
                                    }
                                }

                            }
                        }


                    }
                }
            }
        }

        /// <summary>
        /// Método de actualizacion de una jerarquiaCarpeta
        /// </summary>
        /// <param name="jerarquiaCarpeta"></param>
        public void ActualizarJerarquiaCarpeta(JerarquiaCarpeta jerarquiaCarpeta)
        {
            _contexto.JerarquiasCarpeta.ToList().Find(carpeta => carpeta.Id == jerarquiaCarpeta.Id).Nombre = jerarquiaCarpeta.Nombre;
            AplicarCambios();
        }

        /// <summary>
        /// Borra una carpeta
        /// </summary>
        /// <param name="guidCarpeta">id de la carpeta a borrar</param>
        public void BorrarJerarquiaCarpeta(Guid guidCarpeta)
        {
            _contexto.BorrarJerarquiaCarpeta(guidCarpeta);
        }

        /// <summary>
        /// Borra un documento
        /// </summary>
        /// <param name="guidDocumento">id del documento a borrar</param>
        public void BorrarDocumento(Guid guidDocumento)
        {
            _contexto.BorrarDocumento(guidDocumento);
        }

        /// <summary>
        /// Borra un documento con un tag específico en una carpeta especifica. Si la 
        /// carpeta llegara a tener más de un documento con el mismo tag se borrarán todos
        /// </summary>
        /// <param name="idProyecto">id del Proyecto</param>
        /// <param name="idJerarquiaCarpeta">id de la carpeta</param>
        /// <param name="idDocumentoTag">id del tag del documento a borrar</param>
        public void BorrarDocumentos(Guid idProyecto, Guid idJerarquiaCarpeta, int idDocumentoTag)
        {
            _contexto.BorrarDocumentos(idProyecto, idJerarquiaCarpeta, idDocumentoTag);
        }

        /// <summary>
        /// Inserta una nueva carpeta como subcarpeta de la carpeta padre cuyo guid es dado. Si el padre
        /// no existe nada es insertado
        /// </summary>
        /// <param name="idCarpetaPadre">id carpeta padre</param>
        /// <param name="nombreCarpetaNueva">nombre de nueva carpeta</param>

        public void InsertarCarpetaNueva(Guid idCarpetaPadre, string nombreCarpetaNueva)
        {
            _contexto.InsertarCarpeta(idCarpetaPadre, nombreCarpetaNueva);
        }

        #region IDisposable Members
        /// <summary>
        /// Implementacion de dispose.
        /// </summary>
        public void Dispose()
        {
            if (_contexto != null)
                _contexto.Dispose();
        }

        #endregion


        /// <summary>
        /// Sube de orden los estados de los documentos de un proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void SubirOrdenEstadosDocumentoProyecto(string idProyecto, string idEstadoAprobado, string idEstadoRechazado)
        {
            _contexto.SubirOrdenEstadoDocumentoProyecto(new Guid(idProyecto), new Guid(idEstadoAprobado), new Guid(idEstadoRechazado));
        }

        /// <summary>
        /// Baja de orden los estados de los documentos de un proyecto
        /// </summary>
        /// <param name="idProyecto">Identificador del proyecto</param>
        /// <param name="idEstadoAprobado">Identificador del estado aprobado</param>
        /// <param name="idEstadoRechazado">Identificador del estado rechazado</param>
        public void BajarOrdenEstadosDocumentoProyecto(string idProyecto, string idEstadoAprobado, string idEstadoRechazado)
        {
            _contexto.BajarOrdenEstadoDocumentoProyecto(new Guid(idProyecto), new Guid(idEstadoAprobado), new Guid(idEstadoRechazado));
        }

        /// <summary>
        /// Metodo para cambiar la columna relevante en los documentos que esten en la carpeta indicada
        /// con el tag indicado
        /// </summary>
        /// <param name="idProyecto">id del proyecto</param>
        /// <param name="idJerarquiaCarpeta">id de la carpeta que contiene el archivo</param>
        /// <param name="idDocumentoTag">id del tipo de documento a cambiar</param>
        public void SwitchRelevancia(Guid idProyecto, Guid idJerarquiaCarpeta, int idDocumentoTag)
        {
            //llamar al contexto para relaizar la accion
            _contexto.SwitchRelevancia(idProyecto, idJerarquiaCarpeta, idDocumentoTag);
        }

        /// <summary>
        /// Calcula el porcentaje de documentos creados de un candidato en particular
        /// </summary>
        /// <param name="idCandidato">id del candidato</param>
        public float CalcularProcentajeCandidato(Guid idCandidato)
        {
            ReadOnlyCollection<IEntidadLinqDocumento> documentosCandidato = _contexto.GetDocumentosByCandidato(idCandidato);
            //TODO: Arreglar
            List<IEntidadLinqDocumento> documentosSubidos = documentosCandidato.ToList().FindAll(d => d.IdEstadoDocumentoSeleccionado != _contexto.GetIdEstadoByNombre("Ninguno") && d.Relevante);

            List<IEntidadLinqDocumento> documentosRelevantes = documentosCandidato.ToList().FindAll(d => d.Relevante);

            float porcentaje = (float)documentosSubidos.Count / (float)documentosRelevantes.Count;

            return porcentaje;

        }

        /// <summary>
        /// Retorna el Id de un estado por el nombre, si no lo encuentra retorna null
        /// </summary>
        /// <param name="nombreEstado">nombre del estado a buscar</param>
        /// <returns></returns>
        public Guid? GetIdEstadoByNombre(string nombreEstado)
        {
            return _contexto.GetIdEstadoByNombre(nombreEstado);
        }
    }
}
